package cc.yuxiang.spider;

import java.io.File;
import java.io.IOException;
import java.util.LinkedList;

import cn.hutool.core.text.StrFormatter;
import cn.hutool.core.thread.ThreadUtil;
import jodd.http.HttpRequest;
import jodd.io.FileUtil;
import jodd.io.NetUtil;
import jodd.io.findfile.WildcardFindFile;
import jodd.jerry.Jerry;
import jodd.jerry.JerryFunction;
import jodd.util.Wildcard;
import lombok.Data;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.val;
import lombok.extern.slf4j.Slf4j;

@Data
@Slf4j
@RequiredArgsConstructor
public class NextJav implements Runnable {
	private @NonNull String diskPath;
	private @NonNull Integer page;

	private static final String url = "https://nextjav.com";

	@Override
	public void run() {
		try {
			this.spider();
		} catch (Exception e) {
			log.error("异常:" + page, e);
		}
	}

	private void spider() {
		log.info("爬取:" + url + "/page/" + page);

		val bodyText = HttpRequest.get(url + "/page/" + page).timeout(1000 * 30).connectionTimeout(1000 * 30).send().bodyText();
		log.info("获取到页面结果,页数:" + page);
		val jerry = Jerry.jerry(bodyText);

		jerry.$("div.portfolio_item.status-publish.format-standard.has-post-thumbnail").each(new JerryFunction() {
			public Boolean onNode(Jerry $this, int index) {
				val href = $this.$("a").attr("href");
				val folderName = href.substring(href.lastIndexOf("/") + 1);
				if ("".equals(folderName)) {
					log.info("未知错误,路径:" + href);
					return true;
				}
				val folderPath = StrFormatter.format("{}/{}/", diskPath, folderName);
				log.info("轮询:" + folderName);
				if (!FileUtil.isExistingFolder(new File(folderPath))) {
					log.info("创建目录:" + folderName);
					try {
						FileUtil.mkdir(folderPath);
					} catch (IOException e) {
						e.printStackTrace();
					}
				}

				// 查询是否有torrent文件
				val findAll = WildcardFindFile.create().searchPath(folderPath).findAll();
				for (File f : findAll) {
					if (Wildcard.matchPath(f.getName(), "*.torrent")) {
						log.info("跳过!可能是已经爬取过,存在torrent文件:" + f.getName());
						return true;
					}
				}
				log.info("文件夹名称:" + folderName);
				val bodyText = HttpRequest.get(url + href).send().bodyText();
				val jerry = Jerry.jerry(bodyText);

				val imgesName = new LinkedList<>();
				jerry.$("div.col-md-8.ql_single-portfolio_images div.item").each(new JerryFunction() {
					public Boolean onNode(Jerry $this, int index) {
						String imgPath = $this.$("div.ql_wrap_img a").attr("href");
						String imgName = imgPath.substring(imgPath.lastIndexOf("/") + 1);
						if (!FileUtil.isExistingFile(new File(folderPath + imgName))) {
							try {
								NetUtil.downloadFile(url + imgPath, new File(folderPath + imgName));
								log.info("下载完成!图片名称:" + imgName + ",当前页数:" + page);
								imgesName.add(imgName);
							} catch (IOException e) {
								e.printStackTrace();
							}
							ThreadUtil.sleep(500);
						}
						return true;
					}
				});
				// torrent最后,如果目录下没有这个文件,则需要重新下载
				val url_torrent = jerry.$("a.button.btn.btn-danger.btn-download").attr("href");
				val torrentName = url_torrent.substring(url_torrent.lastIndexOf("/") + 1).replace("nextjav-torrent-", "");
				if (!FileUtil.isExistingFile(new File(folderPath + torrentName))) {
					try {
						NetUtil.downloadFile(url + url_torrent, new File(folderPath + torrentName));
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
				ThreadUtil.sleep(1000);
				return true;
			}
		});
		log.info("结束爬取:" + page);
	}
	
	public static void main(String[] args) throws IOException {
		val diskPath = "D:\\temp";
		//从第2-5,开启多线程吃奶力爬
		for (int i = 2; i < 6; i++) {
			val nextJav = new NextJav(diskPath, i);
			ThreadUtil.execAsync(nextJav);
		}
	}
}